Skip to content
View Article Network

HTML5 Custom Attributes

Introduction

I stumbled upon an article I wrote on 2016/8/1 and decided to back it up here to increase my post count. The content seems to be from the jQuery 1.8 era (jQuery 4 is almost out now, haha). Since it has been over 7 years, I cannot guarantee that the content is fully up to date with current standards.

Explanation

If you have used JavaScript/jQuery plugins or frameworks written by others, you may have noticed some HTML tags containing attributes starting with data- (HTML Attributes). These data- prefixed attributes are custom attributes, meaning they are not predefined by the W3C (World Wide Web Consortium) specifications.

In the early days, it was possible to add non-W3C defined attributes to HTML tags. Although you might see warnings like "Validation ({used html document specification}): Attribute '{custom attribute}' is not a valid attribute of the '{html element}' element," these custom attributes were actually created as HTML Attributes when the page ran. Therefore, you could access them using jQuery's attr() or JavaScript's setAttribute() and getAttribute(). Note that these custom attributes are not synchronized to DOM Properties, so you cannot access them using jQuery's prop(), JavaScript's {DOM}.{Property} = {Value}, or {DOM}["{Property}"] = {Value}. As for the differences between HTML Attributes and DOM Properties, please search for them on Google; I will not cover them here.

The HTML5 specification allows the use of data-{attribute} in HTML elements. This means that if your HTML document declares <!DOCTYPE html> (HTML5 document declaration) and you use attributes starting with data-, you will not see the aforementioned warnings. Since HTML now has custom attributes, JavaScript and jQuery naturally have corresponding syntax for them.

How to Use Custom Attributes

JavaScript

The following content applies to these browser versions:

  1. Internet Explorer: 11+
  2. Chrome: 8+
  3. Firefox: 6+
  4. Opera: 11.1+
  5. Safari: 6+
  6. Android Browser: 4+

dataset

In JavaScript, besides using setAttribute() and getAttribute() to access HTML custom attributes, these custom attributes are converted into an object of type DOMStringMap when the page runs, stored in the DOM's dataset property (DOM Property). This means you can access them using {DOM object}.dataset.{custom attribute}, {DOM object}.dataset["{custom attribute}"], or {DOM object}["dataset"]["{custom attribute}"].

Attribute Naming Rules

When using setAttribute() and getAttribute() to access data- prefixed custom attributes, you still use the full attribute name (HTML Attribute). However, when dataset accesses these custom attributes, the names undergo a transformation based on the following rules:

  1. Remove data-.
  2. Remove every - in the attribute name.
  3. The attribute name is split by - into multiple words and combined using lower camel case. For example, if the attribute is named data-cloudy-wing, the JavaScript access would be {DOM object}.dataset.cloudyWing.

jQuery

The following content applies to these jQuery versions:

  1. jQuery.data(element, key, value): version added: 1.2.3
  2. .data(key, value): version added: 1.2.3
  3. .data(obj): version added: 1.4.3
  4. Support for HTML5 data- attributes: version added: 1.4.3

attr(), prop(), and data()

Since data() originated before HTML5 support, it is clear that data() was not created specifically for custom attributes. It was only made compatible after HTML5 announced custom attributes, so its mechanism is naturally different from JavaScript's dataset. Before version 1.6, when prop() did not exist, if we wanted to use jQuery to store values in the DOM, using attr() would reflect the value in the HTML Tag (you could see the HTML code change in developer tools). However, if we wanted to store sensitive data, attr() was not suitable. Furthermore, HTML Attribute values are strings, so if we wanted to store booleans or numbers, we had to convert them when using attr(). In this case, data() was a good choice (though I wonder why one wouldn't just use JavaScript DOM Properties directly...).

Although data() looks like it attaches data to a DOM object just like prop(), it actually stores the data in jQuery.cache rather than as a DOM Property.

Basically, there are three situations for getting attribute values other than value from HTML Tags using jQuery: use prop() for simple attributes like disabled, use data() for custom attributes starting with data-, and use attr() for everything else.

When setting values, use attr() for non-simple HTML Attributes, data() for data- prefixed custom attributes (though this is just for consistency in getting/setting, it won't actually write back to the HTML Tag), and prop() for simple attributes. As for other cases, although prop() and data() seem similar in purpose, prop() performs better than data(). Unless you don't want the data to be visible from the DOM (when using foreach or console.log() on the DOM), use prop().

Attribute Naming Rules

When using attr() to get a custom attribute, the attribute name is the full name. However, when using data() to get it, the name is slightly different. The rules before ver. 1.5 are as follows:

  1. Remove data-.
  2. All words are lowercase. Perhaps because the difference from JavaScript's dataset naming rules caused confusion, ver. 1.6 and later also support dataset attribute names. This means data-cloudy-wing can be written as data('cloudyWing').

Notes

When getting custom attributes from HTML Tags, you should use data(key) or data(obj). jQuery.data(element, key) is the underlying method for the first two and cannot retrieve custom attributes. However, generally speaking, it is not recommended to use jQuery's underlying methods directly.

When data() retrieves a custom attribute, it determines the data type based on the attribute value. However, if the value starts with 0 for integers or ends with 0 for decimals (e.g., 012.050), versions before 1.7 identified the type as a number, resulting in 12.05. After ver. 1.8, it is identified as a string, and the resulting value is 012.050.

If you want to use JSON format for HTML Tag custom attribute values, the JSON string must use single quotes, and JSON properties must use double quotes. For example: data-wing='{"name": "wing","heigh": 177}'. Only then will data(obj) correctly convert this JSON string into an object.

Comparison of jQuery data() and JavaScript dataset

These two things are fundamentally different and cannot be used interchangeably. data() only compares against custom attributes when a value has not yet been set; all subsequent accesses are stored in jQuery.cache and have no relation to the custom attributes. dataset, on the other hand, accesses the custom attributes every time it is used. You can see the difference if you use developer tools to inspect the HTML code.

In terms of usage, I would recommend using jQuery data() for the following reasons:

  1. data() has better browser support; dataset fails on IE10 and below.
  2. data() provides different data types based on what you provide, whereas dataset only provides strings. data() is more convenient when you want to use boolean values for custom attributes.
  3. data() supports JSON attributes, while dataset does not.

WARNING

This recommendation is from 7 years ago. Nowadays, frontend frameworks are prevalent, and many websites no longer use jQuery.

Change Log

  • 2024-03-09 Initial document creation.